SafetyNet 與 Play Integrity API
intro: why we need these?
現代行動 App、特別是金融、遊戲、數位內容等領域,都要求確保以下幾件事:
- 應用未被篡改:確認執行的 App 是官方簽名、未被修改版
- 裝置環境安全:避免在 root、破解、篡改 ROM 或模擬器上運行
- 避免偽造請求:使伺服端能辨識是合法的 App 與裝置發起請求
傳統來講,App 可以在客戶端做一些檢測(如檢查 root 存在性、檢查可寫文件權限、檢查系統設定等),但這類檢測極易被反作弊工具、hook 或自訂 ROM 躲避。因此 Google 提供了 SafetyNet 機制,進行更強的裝置誠信檢測;而近期則推出了後續框架 Play Integrity API,作為 SafetyNet 的升級與替代方案。
SafetyNet 概念與運作
SafetyNet 基本概念
SafetyNet 是 Google Play Services 提供的安全檢測機制,其中最常被使用的是 SafetyNet Attestation API。這個 API 用來回報裝置是否位於可信環境,包括:
- Bootloader 是否解鎖
- ROM 是否被修改
- Kernel 模組或 root 工具的存在
- 系統完整性(如 Android Verified Boot、dm-verity)
SafetyNet 也有其他子功能,如 reCAPTCHA 驗證、Verify Apps 等。
但 Google 已宣佈,從 2025 年 1 月起,SafetyNet Attestation API 將停止服務 / 被 Play Integrity 取代。
SafetyNet 的流程
簡化流程如下:
App → SafetyNetClient.getClient(...) → SafetyNet.getClient().attest(nonce) → 返回 JWS token (JWT-like) → App 將 token 傳給後端伺服器 → 後端解碼與驗證簽名 → 得出 integrity verdict
- nonce:防重放隨機數
- 返回 JWS token 包含 ctsProfileMatch、basicIntegrity、advice 等欄位
- 後端驗證簽名(Google 的公鑰),決定是否信任該裝置/App
在過去,許多應用以 ctsProfileMatch = true 作為通過標準。但實務上有不少 root 或修改裝置能通過 basicIntegrity 卻不通過 ctsProfileMatch。
因 SafetyNet 存在被繞過的可能,Google 認為它已不足以作為未來主力方案。
Play Integrity API:現代的誠信驗證
Play Integrity API 概念與定位
Play Integrity API 是 Google 為取代 SafetyNet 而設計的新機制,整合裝置完整性(device integrity)、應用完整性(app integrity)與帳戶授權(account / licensing)等多面向驗證。
它能檢測潛在風險互動,例如修改過的 App、非正版安裝、模擬器或未經認證的裝置。
此外,Play Integrity API 支援更多的 verdicts(裁決)與額外欄位,例如 playProtectVerdict、appAccessRiskVerdict、recentDeviceActivity 等。
與 SafetyNet 的差異與升級
| 項目 |
SafetyNet Attestation |
Play Integrity API |
| 停用時間 |
即將停用 |
正式取代 SafetyNet |
| 驗證項目 |
integrity、CTS Profile |
deviceIntegrity、appIntegrity、accountDetails + 額外 signal |
| 回傳格式 |
JWS token |
JWS / JWT token 結合更多欄位 |
| 服務端角色 |
後端驗證簽名 |
後端依 verdict 決策 |
| 擴充性 |
相對受限 |
可新增多種信號與條件判斷 |
舉例來說,Play Integrity API 引入 MEETS_STRONG_INTEGRITY,要求設備具備硬體支持、實施 Android 的安全引導與更新策略。只有在高度安全環境下才可能通過此等級。
Play Integrity API 的流程
流程示意如下:

重點在於:
- nonce 防重放
- 驗證簽名必須在後端做
- 前端僅作傳遞與接收
Google 建議將高敏感操作(如金流、內購)包裝在需要 integrity 判斷的流程中,不要全部流量都依靠 integrity API。
Play Integrity verdicts(裁決)與欄位
Play Integrity 回傳的 JWT payload 中會包含多個 verdict/欄位,可供後端進行策略判斷。主要分類如下:
核心 verdict 分類 (強制)
- deviceIntegrity
- 判斷裝置是否為可信、符合 Google 認證標準
- 可能值:MEETS_STRONG_INTEGRITY、MEETS_DEVICE_INTEGRITY、MEETS_BASIC_INTEGRITY
- appIntegrity
- 判斷 App 是否與 Play Store 上的版本一致、是否未被修改
- accountDetails
- 關於該 Google 帳戶是否安裝或購買該 App
可選 signal 欄位 (進階)
- playProtectVerdict
- 指出 Google Play Protect 判定於裝置上的®違規 App 是否存在
- appAccessRiskVerdict
- 用於檢測 App 使用 overlay、截屏、輔助功能濫用等風險
- recentDeviceActivity
- 用來檢查該裝置近期是否進行大量請求,可能是機器人行為
- deviceRecall(beta)
- environmentDetails
後端可根據這些 verdict 做出細緻的風控策略,例如:
- MEETS_STRONG_INTEGRITY → 正常流程允許
- MEETS_DEVICE_INTEGRITY → 輕度風險,限制某些操作
- MEETS_BASIC_INTEGRITY → 嚴重風險,要求安全警告或拒絕
- 若 playProtectVerdict = UNTRUSTED → 拒絕交易或強制登出
Dev guideline
在 Play Console 啟用
- 在 Google Play Console 中啟用 Play Integrity API
- 申請 API key 並設置授權域名
- 將異動版 Play Integrity 設為應用的一部分
客戶端搭配範例
val integrityManager = IntegrityManagerFactory.create(context)
val nonce = generateNonceFromBackend()
val request = IntegrityManagerRequest.builder()
.setNonce(nonce.toByteArray())
.build()
integrityManager.requestIntegrityToken(request)
.addOnSuccessListener { response ->
val token = response.token()
// Send token + nonce to your backend
}
.addOnFailureListener { e ->
// 處理失敗
}
要注意:
- nonce 必須每次不同
- 要有後端來驗證 JWT
- 前端不要僅依 token 決定封鎖,應由後端策略決定
後端驗證流程
後端收到 token 後應該:
- 驗證 JWT 簽名/Google 公鑰
- 驗證 nonce 是否正確、未重放
- 檢查 timestampMs 是否在合理時段
- 解析 deviceIntegrity、appIntegrity、accountDetails 等
- 根據風控策略決定該用戶是否可執行某些操作
建議策略:
- 不要全盤封鎖根裝置,改為限制高風險操作(例如交易、金流)
- 慢慢升級驗證強度,避免大量用戶被誤封鎖
- 記錄 verdict 分布,以做後續調整
限制、風險與攻擊可能性
Play Integrity API 雖然比 SafetyNet 強化許多,但仍有一些限制與風險須注意:
- 流量配額限制
- 預設每天 10,000 次請求(可向 Google 申請提高)
- 超出後請求可能被拒絕或延後
- 較高延遲
- 特別在 “classic” 模式下或首次啟用時,token 較慢。
- 設備兼容性限制
- 僅支援 Google 認證裝置,若裝置無法使用 Google Play Services,該機制無法運作
- 可能被繞過 / spoof
- 對抗高階攻擊者仍可能有方法繞過(例如偽造 response、重放、root 隱藏技術)
- 缺乏極細節信號
- Play Integrity 不會返回完整惡意應用清單;相較 SafetyNet 的 listHarmfulApps() 方法被廢除
- 鎖定 Google 生態系統
- 非 Play Store 安裝、AOSP 裝置、或無 Google Play Services 的環境可能無法通過 integrity 檢測
questions
- SafetyNet Attestation 為何被淘汰?它的主要缺點是什麼?
- 信號較弱、容易被繞過、缺乏豐富的 verdict
- Google 推動 Play Integrity 作為更強驗證機制
- Play Integrity API 的三大核心驗證維度是什麼?
- deviceIntegrity
- appIntegrity
- accountDetails
- nonce 在 Integrity API 中的作用?
- 若後端收到無法通過 integrity 的判決,應如何處理?
- 不應直接封鎖,用階段性限制方式(例如:禁止金流、顯示警告、要求升級)
- 可要求用戶重新驗證或檢查系統環境
- Play Integrity API 的限制與風險有哪些?
- 配額限制、延遲、兼容性、繞過可能性、鎖定 Google 生態系統
- 為什麼必須在後端驗證 token?不能只在客戶端驗證嗎?
- 客戶端驗證容易被逆向或篡改
- 後端可安全驗證簽名、nonce、timestamp,做統一策略
- Play Integrity API 和 Keymaster / TEE / StrongBox 有什麼關係?
- Integrity API 可利用硬體安全 (如 hardware-attested integrity) 作為一部分驗證信號
- Integrity API 在 client 端利用 TEE / Key attestation 支撐信任根 (root of trust)
figs
SafetyNet → Play Integrity 演進對比圖

Play Integrity API 流程時序圖

系統整合示意圖
+----------------------+
| Application |
| (Invoke Integrity API)|
+----------|-----------+
|
+----------v-------------------+
| Google Play Services |
| (Integrity SDK + DroidGuard) |
+----------|-------------------+
|
+----------v-------------------+
| Google Integrity Server |
+----------|-------------------+
|
+----------v---------------+
| Developer Backend Server |
+--------------------------+
summary
- SafetyNet Attestation 是 Google 早期提供的驗證機制,但已逐漸被 Play Integrity API 所取代
- Play Integrity API 是更全面的裝置與應用誠信驗證框架,整合更多 signal 與策略選擇
- 開發者務必透過 後端驗證 token、設計合理風控策略,而非僅在客戶端做保護
- 要注意配額、兼容性、延遲與繞過風險,不宜將 integrity 作為唯一安全機制
- 最佳做法是:將 Integrity 作為多層式安全架構的一環,與權限檢查、加密、行為風控等結合使用